#ifndef COMPACTGRAPHGENERATOR_H_
#define COMPACTGRAPHGENERATOR_H_

#include "IGraphGenerator.h"

#include "CompactGraph.h"


namespace
{

void deleteNonStrGraph( GRAPH_SUPPORT_NS::Graph * compactGraph )
{
	delete compactGraph;
}

}

namespace native_orbitor
{

template< typename SubGeneratorT >
class CompactGraphGenerator : public native_orbitor::IGraphGenerator
{
public:
	virtual std::auto_ptr< GraphPointerGuard > generateGraph(
			SettingsMap settingsMap )
	{
		using namespace GRAPH_SUPPORT_NS;
		using namespace GRAPH_SUPPORT_NS::impls::wrap_igraph;

		typedef typename SubGeneratorT::Graph SrcGraph;
		typedef typename SrcGraph::GrVertex GrVertex;
		typedef typename SrcGraph::GrEdgePtr GrEdgePtr;
		typedef typename SrcGraph::VertexIterator VertexIterator;
		typedef typename SrcGraph::EdgeIterator EdgeIterator;
		typedef typename SrcGraph::EdgeAttributes EdgeAttributes;
		// TODO: graph name convention
		typedef WrapIGraph< EdgeAttributes > TheWrapGraph;

		std::auto_ptr< GraphPointerGuard > srcGrAPtr = subGenerator.generateGraph( settingsMap );
		SrcGraph * srcGrPtr = dynamic_cast< SrcGraph * >( srcGrAPtr->getAbstractGraphPtr() );
		assert( srcGrPtr );
		SrcGraph & srcGr = * srcGrPtr;

		std::vector< GrVertex > vertices( srcGr.getVertexCount() );
		int edgesCount = 0;
		VertexIterator vsit = srcGr.getVerticesEnd();
		for ( VertexIterator vit = srcGr.getVerticesBeg(); vit != vsit; ++vit )
		{
			EdgeIterator esit = srcGr.getEdgsEnd( * vit );
			for ( EdgeIterator eit = srcGr.getEdgsBeg( * vit ); eit != esit; ++eit )
			{
				edgesCount++;
			}
		}

		std::auto_ptr< CompactGraph > resultPtr( new CompactGraph( srcGr.getVertexCount(), edgesCount ) );
		CompactGraph & gr = * resultPtr;
		vsit = srcGr.getVerticesEnd();
		for ( VertexIterator vit = srcGr.getVerticesBeg(); vit != vsit; ++vit )
		{
			EdgeIterator esit = srcGr.getEdgsEnd( * vit );
			for ( EdgeIterator eit = srcGr.getEdgsBeg( * vit ); eit != esit; ++eit )
			{
				gr.addEdge( * vit, ( * eit )->end() );
			}
		}

		return std::auto_ptr< GraphPointerGuard >( new GraphPointerGuard( resultPtr.release(), & deleteNonStrGraph ) );
	}

private:
	SubGeneratorT subGenerator;
};

}

#endif /* COMPACTGRAPHGENERATOR_H_ */
